1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package com.google.common.collect;
18
19 import static com.google.common.base.Preconditions.checkNotNull;
20
21 import com.google.common.annotations.Beta;
22 import com.google.common.annotations.GwtCompatible;
23
24 import java.io.Serializable;
25 import java.util.Collection;
26 import java.util.Comparator;
27 import java.util.Iterator;
28 import java.util.LinkedHashMap;
29 import java.util.List;
30 import java.util.Map;
31 import java.util.Map.Entry;
32 import java.util.Set;
33 import java.util.SortedSet;
34
35 import javax.annotation.Nullable;
36
37
38
39
40
41
42
43
44 @Beta
45 @GwtCompatible
46 public final class MapConstraints {
47 private MapConstraints() {}
48
49
50
51
52
53 public static MapConstraint<Object, Object> notNull() {
54 return NotNullMapConstraint.INSTANCE;
55 }
56
57
58 private enum NotNullMapConstraint implements MapConstraint<Object, Object> {
59 INSTANCE;
60
61 @Override
62 public void checkKeyValue(Object key, Object value) {
63 checkNotNull(key);
64 checkNotNull(value);
65 }
66
67 @Override public String toString() {
68 return "Not null";
69 }
70 }
71
72
73
74
75
76
77
78
79
80
81
82
83
84 public static <K, V> Map<K, V> constrainedMap(
85 Map<K, V> map, MapConstraint<? super K, ? super V> constraint) {
86 return new ConstrainedMap<K, V>(map, constraint);
87 }
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105 public static <K, V> Multimap<K, V> constrainedMultimap(
106 Multimap<K, V> multimap, MapConstraint<? super K, ? super V> constraint) {
107 return new ConstrainedMultimap<K, V>(multimap, constraint);
108 }
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126 public static <K, V> ListMultimap<K, V> constrainedListMultimap(
127 ListMultimap<K, V> multimap,
128 MapConstraint<? super K, ? super V> constraint) {
129 return new ConstrainedListMultimap<K, V>(multimap, constraint);
130 }
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147 public static <K, V> SetMultimap<K, V> constrainedSetMultimap(
148 SetMultimap<K, V> multimap,
149 MapConstraint<? super K, ? super V> constraint) {
150 return new ConstrainedSetMultimap<K, V>(multimap, constraint);
151 }
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168 public static <K, V> SortedSetMultimap<K, V> constrainedSortedSetMultimap(
169 SortedSetMultimap<K, V> multimap,
170 MapConstraint<? super K, ? super V> constraint) {
171 return new ConstrainedSortedSetMultimap<K, V>(multimap, constraint);
172 }
173
174
175
176
177
178
179
180
181
182
183 private static <K, V> Entry<K, V> constrainedEntry(
184 final Entry<K, V> entry,
185 final MapConstraint<? super K, ? super V> constraint) {
186 checkNotNull(entry);
187 checkNotNull(constraint);
188 return new ForwardingMapEntry<K, V>() {
189 @Override protected Entry<K, V> delegate() {
190 return entry;
191 }
192 @Override public V setValue(V value) {
193 constraint.checkKeyValue(getKey(), value);
194 return entry.setValue(value);
195 }
196 };
197 }
198
199
200
201
202
203
204
205
206
207
208
209 private static <K, V> Entry<K, Collection<V>> constrainedAsMapEntry(
210 final Entry<K, Collection<V>> entry,
211 final MapConstraint<? super K, ? super V> constraint) {
212 checkNotNull(entry);
213 checkNotNull(constraint);
214 return new ForwardingMapEntry<K, Collection<V>>() {
215 @Override protected Entry<K, Collection<V>> delegate() {
216 return entry;
217 }
218 @Override public Collection<V> getValue() {
219 return Constraints.constrainedTypePreservingCollection(
220 entry.getValue(), new Constraint<V>() {
221 @Override
222 public V checkElement(V value) {
223 constraint.checkKeyValue(getKey(), value);
224 return value;
225 }
226 });
227 }
228 };
229 }
230
231
232
233
234
235
236
237
238
239
240
241
242
243 private static <K, V> Set<Entry<K, Collection<V>>> constrainedAsMapEntries(
244 Set<Entry<K, Collection<V>>> entries,
245 MapConstraint<? super K, ? super V> constraint) {
246 return new ConstrainedAsMapEntries<K, V>(entries, constraint);
247 }
248
249
250
251
252
253
254
255
256
257
258
259
260
261 private static <K, V> Collection<Entry<K, V>> constrainedEntries(
262 Collection<Entry<K, V>> entries,
263 MapConstraint<? super K, ? super V> constraint) {
264 if (entries instanceof Set) {
265 return constrainedEntrySet((Set<Entry<K, V>>) entries, constraint);
266 }
267 return new ConstrainedEntries<K, V>(entries, constraint);
268 }
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284 private static <K, V> Set<Entry<K, V>> constrainedEntrySet(
285 Set<Entry<K, V>> entries,
286 MapConstraint<? super K, ? super V> constraint) {
287 return new ConstrainedEntrySet<K, V>(entries, constraint);
288 }
289
290
291 static class ConstrainedMap<K, V> extends ForwardingMap<K, V> {
292 private final Map<K, V> delegate;
293 final MapConstraint<? super K, ? super V> constraint;
294 private transient Set<Entry<K, V>> entrySet;
295
296 ConstrainedMap(
297 Map<K, V> delegate, MapConstraint<? super K, ? super V> constraint) {
298 this.delegate = checkNotNull(delegate);
299 this.constraint = checkNotNull(constraint);
300 }
301 @Override protected Map<K, V> delegate() {
302 return delegate;
303 }
304 @Override public Set<Entry<K, V>> entrySet() {
305 Set<Entry<K, V>> result = entrySet;
306 if (result == null) {
307 entrySet = result =
308 constrainedEntrySet(delegate.entrySet(), constraint);
309 }
310 return result;
311 }
312 @Override public V put(K key, V value) {
313 constraint.checkKeyValue(key, value);
314 return delegate.put(key, value);
315 }
316 @Override public void putAll(Map<? extends K, ? extends V> map) {
317 delegate.putAll(checkMap(map, constraint));
318 }
319 }
320
321
322
323
324
325
326
327
328
329
330
331
332 public static <K, V> BiMap<K, V> constrainedBiMap(
333 BiMap<K, V> map, MapConstraint<? super K, ? super V> constraint) {
334 return new ConstrainedBiMap<K, V>(map, null, constraint);
335 }
336
337
338 private static class ConstrainedBiMap<K, V> extends ConstrainedMap<K, V>
339 implements BiMap<K, V> {
340
341
342
343
344
345
346
347
348
349
350
351
352 volatile BiMap<V, K> inverse;
353
354 ConstrainedBiMap(BiMap<K, V> delegate, @Nullable BiMap<V, K> inverse,
355 MapConstraint<? super K, ? super V> constraint) {
356 super(delegate, constraint);
357 this.inverse = inverse;
358 }
359
360 @Override protected BiMap<K, V> delegate() {
361 return (BiMap<K, V>) super.delegate();
362 }
363
364 @Override
365 public V forcePut(K key, V value) {
366 constraint.checkKeyValue(key, value);
367 return delegate().forcePut(key, value);
368 }
369
370 @Override
371 public BiMap<V, K> inverse() {
372 if (inverse == null) {
373 inverse = new ConstrainedBiMap<V, K>(delegate().inverse(), this,
374 new InverseConstraint<V, K>(constraint));
375 }
376 return inverse;
377 }
378
379 @Override public Set<V> values() {
380 return delegate().values();
381 }
382 }
383
384
385 private static class InverseConstraint<K, V> implements MapConstraint<K, V> {
386 final MapConstraint<? super V, ? super K> constraint;
387
388 public InverseConstraint(MapConstraint<? super V, ? super K> constraint) {
389 this.constraint = checkNotNull(constraint);
390 }
391 @Override
392 public void checkKeyValue(K key, V value) {
393 constraint.checkKeyValue(value, key);
394 }
395 }
396
397
398 private static class ConstrainedMultimap<K, V>
399 extends ForwardingMultimap<K, V> implements Serializable {
400 final MapConstraint<? super K, ? super V> constraint;
401 final Multimap<K, V> delegate;
402 transient Collection<Entry<K, V>> entries;
403 transient Map<K, Collection<V>> asMap;
404
405 public ConstrainedMultimap(Multimap<K, V> delegate,
406 MapConstraint<? super K, ? super V> constraint) {
407 this.delegate = checkNotNull(delegate);
408 this.constraint = checkNotNull(constraint);
409 }
410
411 @Override protected Multimap<K, V> delegate() {
412 return delegate;
413 }
414
415 @Override public Map<K, Collection<V>> asMap() {
416 Map<K, Collection<V>> result = asMap;
417 if (result == null) {
418 final Map<K, Collection<V>> asMapDelegate = delegate.asMap();
419
420 asMap = result = new ForwardingMap<K, Collection<V>>() {
421 Set<Entry<K, Collection<V>>> entrySet;
422 Collection<Collection<V>> values;
423
424 @Override protected Map<K, Collection<V>> delegate() {
425 return asMapDelegate;
426 }
427
428 @Override public Set<Entry<K, Collection<V>>> entrySet() {
429 Set<Entry<K, Collection<V>>> result = entrySet;
430 if (result == null) {
431 entrySet = result = constrainedAsMapEntries(
432 asMapDelegate.entrySet(), constraint);
433 }
434 return result;
435 }
436
437 @SuppressWarnings("unchecked")
438 @Override public Collection<V> get(Object key) {
439 try {
440 Collection<V> collection = ConstrainedMultimap.this.get((K) key);
441 return collection.isEmpty() ? null : collection;
442 } catch (ClassCastException e) {
443 return null;
444 }
445 }
446
447 @Override public Collection<Collection<V>> values() {
448 Collection<Collection<V>> result = values;
449 if (result == null) {
450 values = result = new ConstrainedAsMapValues<K, V>(
451 delegate().values(), entrySet());
452 }
453 return result;
454 }
455
456 @Override public boolean containsValue(Object o) {
457 return values().contains(o);
458 }
459 };
460 }
461 return result;
462 }
463
464 @Override public Collection<Entry<K, V>> entries() {
465 Collection<Entry<K, V>> result = entries;
466 if (result == null) {
467 entries = result = constrainedEntries(delegate.entries(), constraint);
468 }
469 return result;
470 }
471
472 @Override public Collection<V> get(final K key) {
473 return Constraints.constrainedTypePreservingCollection(
474 delegate.get(key), new Constraint<V>() {
475 @Override
476 public V checkElement(V value) {
477 constraint.checkKeyValue(key, value);
478 return value;
479 }
480 });
481 }
482
483 @Override public boolean put(K key, V value) {
484 constraint.checkKeyValue(key, value);
485 return delegate.put(key, value);
486 }
487
488 @Override public boolean putAll(K key, Iterable<? extends V> values) {
489 return delegate.putAll(key, checkValues(key, values, constraint));
490 }
491
492 @Override public boolean putAll(
493 Multimap<? extends K, ? extends V> multimap) {
494 boolean changed = false;
495 for (Entry<? extends K, ? extends V> entry : multimap.entries()) {
496 changed |= put(entry.getKey(), entry.getValue());
497 }
498 return changed;
499 }
500
501 @Override public Collection<V> replaceValues(
502 K key, Iterable<? extends V> values) {
503 return delegate.replaceValues(key, checkValues(key, values, constraint));
504 }
505 }
506
507
508 private static class ConstrainedAsMapValues<K, V>
509 extends ForwardingCollection<Collection<V>> {
510 final Collection<Collection<V>> delegate;
511 final Set<Entry<K, Collection<V>>> entrySet;
512
513
514
515
516
517 ConstrainedAsMapValues(Collection<Collection<V>> delegate,
518 Set<Entry<K, Collection<V>>> entrySet) {
519 this.delegate = delegate;
520 this.entrySet = entrySet;
521 }
522 @Override protected Collection<Collection<V>> delegate() {
523 return delegate;
524 }
525
526 @Override public Iterator<Collection<V>> iterator() {
527 final Iterator<Entry<K, Collection<V>>> iterator = entrySet.iterator();
528 return new Iterator<Collection<V>>() {
529 @Override
530 public boolean hasNext() {
531 return iterator.hasNext();
532 }
533 @Override
534 public Collection<V> next() {
535 return iterator.next().getValue();
536 }
537 @Override
538 public void remove() {
539 iterator.remove();
540 }
541 };
542 }
543
544 @Override public Object[] toArray() {
545 return standardToArray();
546 }
547 @Override public <T> T[] toArray(T[] array) {
548 return standardToArray(array);
549 }
550 @Override public boolean contains(Object o) {
551 return standardContains(o);
552 }
553 @Override public boolean containsAll(Collection<?> c) {
554 return standardContainsAll(c);
555 }
556 @Override public boolean remove(Object o) {
557 return standardRemove(o);
558 }
559 @Override public boolean removeAll(Collection<?> c) {
560 return standardRemoveAll(c);
561 }
562 @Override public boolean retainAll(Collection<?> c) {
563 return standardRetainAll(c);
564 }
565 }
566
567
568 private static class ConstrainedEntries<K, V>
569 extends ForwardingCollection<Entry<K, V>> {
570 final MapConstraint<? super K, ? super V> constraint;
571 final Collection<Entry<K, V>> entries;
572
573 ConstrainedEntries(Collection<Entry<K, V>> entries,
574 MapConstraint<? super K, ? super V> constraint) {
575 this.entries = entries;
576 this.constraint = constraint;
577 }
578 @Override protected Collection<Entry<K, V>> delegate() {
579 return entries;
580 }
581
582 @Override public Iterator<Entry<K, V>> iterator() {
583 final Iterator<Entry<K, V>> iterator = entries.iterator();
584 return new ForwardingIterator<Entry<K, V>>() {
585 @Override public Entry<K, V> next() {
586 return constrainedEntry(iterator.next(), constraint);
587 }
588 @Override protected Iterator<Entry<K, V>> delegate() {
589 return iterator;
590 }
591 };
592 }
593
594
595
596 @Override public Object[] toArray() {
597 return standardToArray();
598 }
599 @Override public <T> T[] toArray(T[] array) {
600 return standardToArray(array);
601 }
602 @Override public boolean contains(Object o) {
603 return Maps.containsEntryImpl(delegate(), o);
604 }
605 @Override public boolean containsAll(Collection<?> c) {
606 return standardContainsAll(c);
607 }
608 @Override public boolean remove(Object o) {
609 return Maps.removeEntryImpl(delegate(), o);
610 }
611 @Override public boolean removeAll(Collection<?> c) {
612 return standardRemoveAll(c);
613 }
614 @Override public boolean retainAll(Collection<?> c) {
615 return standardRetainAll(c);
616 }
617 }
618
619
620 static class ConstrainedEntrySet<K, V>
621 extends ConstrainedEntries<K, V> implements Set<Entry<K, V>> {
622 ConstrainedEntrySet(Set<Entry<K, V>> entries,
623 MapConstraint<? super K, ? super V> constraint) {
624 super(entries, constraint);
625 }
626
627
628
629 @Override public boolean equals(@Nullable Object object) {
630 return Sets.equalsImpl(this, object);
631 }
632
633 @Override public int hashCode() {
634 return Sets.hashCodeImpl(this);
635 }
636 }
637
638
639 static class ConstrainedAsMapEntries<K, V>
640 extends ForwardingSet<Entry<K, Collection<V>>> {
641 private final MapConstraint<? super K, ? super V> constraint;
642 private final Set<Entry<K, Collection<V>>> entries;
643
644 ConstrainedAsMapEntries(Set<Entry<K, Collection<V>>> entries,
645 MapConstraint<? super K, ? super V> constraint) {
646 this.entries = entries;
647 this.constraint = constraint;
648 }
649
650 @Override protected Set<Entry<K, Collection<V>>> delegate() {
651 return entries;
652 }
653
654 @Override public Iterator<Entry<K, Collection<V>>> iterator() {
655 final Iterator<Entry<K, Collection<V>>> iterator = entries.iterator();
656 return new ForwardingIterator<Entry<K, Collection<V>>>() {
657 @Override public Entry<K, Collection<V>> next() {
658 return constrainedAsMapEntry(iterator.next(), constraint);
659 }
660 @Override protected Iterator<Entry<K, Collection<V>>> delegate() {
661 return iterator;
662 }
663 };
664 }
665
666
667
668 @Override public Object[] toArray() {
669 return standardToArray();
670 }
671
672 @Override public <T> T[] toArray(T[] array) {
673 return standardToArray(array);
674 }
675
676 @Override public boolean contains(Object o) {
677 return Maps.containsEntryImpl(delegate(), o);
678 }
679
680 @Override public boolean containsAll(Collection<?> c) {
681 return standardContainsAll(c);
682 }
683
684 @Override public boolean equals(@Nullable Object object) {
685 return standardEquals(object);
686 }
687
688 @Override public int hashCode() {
689 return standardHashCode();
690 }
691
692 @Override public boolean remove(Object o) {
693 return Maps.removeEntryImpl(delegate(), o);
694 }
695
696 @Override public boolean removeAll(Collection<?> c) {
697 return standardRemoveAll(c);
698 }
699
700 @Override public boolean retainAll(Collection<?> c) {
701 return standardRetainAll(c);
702 }
703 }
704
705 private static class ConstrainedListMultimap<K, V>
706 extends ConstrainedMultimap<K, V> implements ListMultimap<K, V> {
707 ConstrainedListMultimap(ListMultimap<K, V> delegate,
708 MapConstraint<? super K, ? super V> constraint) {
709 super(delegate, constraint);
710 }
711 @Override public List<V> get(K key) {
712 return (List<V>) super.get(key);
713 }
714 @Override public List<V> removeAll(Object key) {
715 return (List<V>) super.removeAll(key);
716 }
717 @Override public List<V> replaceValues(
718 K key, Iterable<? extends V> values) {
719 return (List<V>) super.replaceValues(key, values);
720 }
721 }
722
723 private static class ConstrainedSetMultimap<K, V>
724 extends ConstrainedMultimap<K, V> implements SetMultimap<K, V> {
725 ConstrainedSetMultimap(SetMultimap<K, V> delegate,
726 MapConstraint<? super K, ? super V> constraint) {
727 super(delegate, constraint);
728 }
729 @Override public Set<V> get(K key) {
730 return (Set<V>) super.get(key);
731 }
732 @Override public Set<Map.Entry<K, V>> entries() {
733 return (Set<Map.Entry<K, V>>) super.entries();
734 }
735 @Override public Set<V> removeAll(Object key) {
736 return (Set<V>) super.removeAll(key);
737 }
738 @Override public Set<V> replaceValues(
739 K key, Iterable<? extends V> values) {
740 return (Set<V>) super.replaceValues(key, values);
741 }
742 }
743
744 private static class ConstrainedSortedSetMultimap<K, V>
745 extends ConstrainedSetMultimap<K, V> implements SortedSetMultimap<K, V> {
746 ConstrainedSortedSetMultimap(SortedSetMultimap<K, V> delegate,
747 MapConstraint<? super K, ? super V> constraint) {
748 super(delegate, constraint);
749 }
750 @Override public SortedSet<V> get(K key) {
751 return (SortedSet<V>) super.get(key);
752 }
753 @Override public SortedSet<V> removeAll(Object key) {
754 return (SortedSet<V>) super.removeAll(key);
755 }
756 @Override public SortedSet<V> replaceValues(
757 K key, Iterable<? extends V> values) {
758 return (SortedSet<V>) super.replaceValues(key, values);
759 }
760 @Override
761 public Comparator<? super V> valueComparator() {
762 return ((SortedSetMultimap<K, V>) delegate()).valueComparator();
763 }
764 }
765
766 private static <K, V> Collection<V> checkValues(K key,
767 Iterable<? extends V> values,
768 MapConstraint<? super K, ? super V> constraint) {
769 Collection<V> copy = Lists.newArrayList(values);
770 for (V value : copy) {
771 constraint.checkKeyValue(key, value);
772 }
773 return copy;
774 }
775
776 private static <K, V> Map<K, V> checkMap(Map<? extends K, ? extends V> map,
777 MapConstraint<? super K, ? super V> constraint) {
778 Map<K, V> copy = new LinkedHashMap<K, V>(map);
779 for (Entry<K, V> entry : copy.entrySet()) {
780 constraint.checkKeyValue(entry.getKey(), entry.getValue());
781 }
782 return copy;
783 }
784 }